package cn.kent.high.juc.threadPool;

import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;

import java.util.List;

/**
 * 线程池测试类
 * 使用了guava的MoreExecutors代替了jdk自带的Executors工具类(用于创建线程池)
 *
 * 线程池巧妙的使用了一个原子类AtomicLong变量来记录线程池状态和线程池中的线程个数，
 * 通过线程池状态来控制任务的执行，每个Worker线程可以处理多个任务。
 * 线程池通过线程的复用减少了线程创建和销毁的开销。
 */
public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        System.out.println(test());
    }

    private static String test() {
        List<ListenableFuture<String>> futures = Lists.newArrayList();
        futures.add(ThreadPoolUtil.listeningExecutorForRemote.submit(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println(i);
            }
            return "success";
        }));
        final ListenableFuture<List<String>> resultsFuture = Futures.successfulAsList(futures);
        try {//加入到futures的都执行完毕
            List<String> strings = resultsFuture.get();
            System.out.println(strings);
        } catch (Exception e) {
            // log.error("error message:" + e.getMessage(), "");
        } finally {

        }
        return "success";
    }
}

// public void execute(Runnable command) {
//     if (command == null) // 1.任务为空返回NPE
//         throw new NullPointerException();
//     /*
//      * Proceed in 3 steps:
//      *
//      * 1. If fewer than corePoolSize threads are running, try to
//      * start a new thread with the given command as its first
//      * task.  The call to addWorker atomically checks runState and
//      * workerCount, and so prevents false alarms that would add
//      * threads when it shouldn't, by returning false.
//      *
//      * 2. If a task can be successfully queued, then we still need
//      * to double-check whether we should have added a thread
//      * (because existing ones died since last checking) or that
//      * the pool shut down since entry into this method. So we
//      * recheck state and if necessary roll back the enqueuing if
//      * stopped, or start a new thread if there are none.
//      *
//      * 3. If we cannot queue task, then we try to add a new
//      * thread.  If it fails, we know we are shut down or saturated
//      * and so reject the task.
//      */
//     int c = ctl.get(); // 获取当前线程池的状态+线程个数变量的组合值
//     if (workerCountOf(c) < corePoolSize) { // 当前线程池中线程个数是否小于 corePoolSize， 小于则开启线程运行
//         if (addWorker(command, true))
//             return;
//         c = ctl.get();
//     }
//     if (isRunning(c) && workQueue.offer(command)) { // 如果线程池处于RUNNING状态，则添加任务到阻塞队列
//         int recheck = ctl.get(); // 二次检查
//         if (! isRunning(recheck) && remove(command)) // 如果当前线程不处于RUNNING状态则从队列中删除任务，并执行拒绝策略
//             reject(command);
//         else if (workerCountOf(recheck) == 0) // 否则如果当前线程池为空，则添加一个线程
//             addWorker(null, false);
//     }
//     else if (!addWorker(command, false)) // 如果队列满，则新增线程，新增失败则执行拒绝策略
//         reject(command);
// }

// public void shutdown() {
//     final ReentrantLock mainLock = this.mainLock;
//     mainLock.lock();
//     try {
//         checkShutdownAccess(); // 权限检查
//         advanceRunState(SHUTDOWN); // 设置当前线程状态为SHUTDOWN，如果已经是SHUTDOWN则直接返回
//         interruptIdleWorkers(); // 设置中断标志
//         onShutdown(); // hook for ScheduledThreadPoolExecutor
//     } finally {
//         mainLock.unlock();
//     }
//     tryTerminate(); // 尝试将状态修改为 TERMINATED
// }

// public List<Runnable> shutdownNow() {
//     List<Runnable> tasks;
//     final ReentrantLock mainLock = this.mainLock;
//     mainLock.lock();
//     try {
//         checkShutdownAccess(); // 权限检查
//         interruptWorkers(); // 中断所有线程(空闲线程和正在执行任务的线程)
//         advanceRunState(STOP); // 设置线程池状态为STOP
//         tasks = drainQueue(); // 将队列任务移动到tasks中
//     } finally {
//         mainLock.unlock();
//     }
//     tryTerminate();
//     return tasks;
// }

// public boolean awaitTermination(long timeout, TimeUnit unit)
//         throws InterruptedException {
//     long nanos = unit.toNanos(timeout);
//     final ReentrantLock mainLock = this.mainLock;
//     mainLock.lock();
//     try {
//         for (;;) {
//             if (runStateAtLeast(ctl.get(), TERMINATED)) // 判断状态是否至少是TERMINATED状态，是则直接返回，否则说明线程池中还有线程在执行
//                 return true;
//             if (nanos <= 0) // 超时时间是否小于等于0，小于说明无需等待则直接返回，否则调用条件变量termination.awaitNanos，以期望在这段时间内将状态修改为TERMINATED
//                 return false;
//             nanos = termination.awaitNanos(nanos);
//         }
//     } finally {
//         mainLock.unlock();
//     }
// }

